package db.access;

import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import common.enums.AnswerEnum;
import common.enums.HeightEnum;
import common.interfaces.DBInterface;
import common.types.FictionalCharacter;
import common.types.Pair;
import common.types.StatisticsEntry;

public class StubDBImpl implements DBInterface {
	
	private List<FictionalCharacter> characters;
	private static int sessionID = 1;
	private int questionsCounter = 0;
	private Date lastTimeStamp = new Date();
	
	public StubDBImpl() {
		characters = new ArrayList<FictionalCharacter>();
		FictionalCharacter fictionalCharacter = new FictionalCharacter(12, "Nir Biran");
		fictionalCharacter.setChildren(createSet("Amit", "Oded"));
		fictionalCharacter.setEducation(createSet("TAU"));
		fictionalCharacter.setGender("Male");
		fictionalCharacter.setHeight(HeightEnum.FROM_175_TO_200);
		fictionalCharacter.setPowersOrAbilities(createSet("Watch TV", "Recognize candies"));
		fictionalCharacter.setQuotations(createSet("Where is the newspaper??"));
		characters.add(fictionalCharacter);
		
		FictionalCharacter fictionalCharacter2 = new FictionalCharacter(34, "Dan Kilman");
		fictionalCharacter2.setParents(createSet("Gilad","Ran"));
		fictionalCharacter2.setEducation(createSet("TAUTAU"));
		fictionalCharacter2.setGender("Male");
		fictionalCharacter2.setHeight(HeightEnum.ABOVE_200CM);
		fictionalCharacter2.setPowersOrAbilities(createSet("Scala", "Python", "Java script"));
		fictionalCharacter2.setRank(createSet("Master"));
		characters.add(fictionalCharacter2);
		
		characters.add(new FictionalCharacter(56, "Ofer"));
		characters.add(new FictionalCharacter(78, 90, "Alon Horowitz"));
	}
	
	private Set<String> createSet(String... str) {
		Set<String> set = new HashSet<String>();
		for (String string : str) {
			set.add(string);
		}
		return set;
	}

	@Override
	public void cleanGameSession(int SID) throws Exception {}

	@Override
	public boolean createCharacter(FictionalCharacter character) throws Exception {
		for (FictionalCharacter c : characters) {
			if (c.equals(character)) {
				return false;
			}
		}
		characters.add(character);
		return true;
	}

	@Override
	public Pair<String, Integer> getBestCut(int SID, int index) throws Exception {
		return new Pair<String, Integer>("flight", 1);
	}

	@Override
	public Pair<Integer, String> getBestGuess(int SID) throws Exception {
		return new Pair<Integer,String>(characters.get(0).getCharacterID(),
		        characters.get(0).getName()); 
	}

	@Override
	public int getNewGameSessionID() {
		sessionID++;
		questionsCounter = 0;
		return sessionID-1;
	}

	@Override
	public String getQuestionTemplate(int PID) throws Exception {
		return "Does your character as the ability to <0>?";
	}

	@Override
	public boolean isGuessReady(int SID) throws Exception {
		questionsCounter++;
		return questionsCounter > 3;
	}

	@Override
	public void makeCut(int SID, int PID, AnswerEnum answer) throws Exception {}

	@Override
	public Pair<List<FictionalCharacter>, Integer> queryCharacter(String name, int limit) throws Exception {
		List<FictionalCharacter> resCharacters = new ArrayList<FictionalCharacter>();
		for(FictionalCharacter fc : characters){
			
			if(resCharacters.size() == limit){
				break;
			}
			
			if(fc.getName().indexOf(name) != -1){
				resCharacters.add((FictionalCharacter) fc.clone());
			}
		}
		return new Pair<List<FictionalCharacter>, Integer>(resCharacters, resCharacters.size());
	}

	@Override
	public boolean removeCharacter(int CID) throws Exception {
		for (Iterator<FictionalCharacter> iterator = characters.iterator(); iterator.hasNext();) {
			FictionalCharacter c = (FictionalCharacter) iterator.next();
			if (c.getCharacterID() == CID) {
				iterator.remove();
				return true;
			}
		}
		return false;
	}

	@Override
	public void runAnalysis(int SID) throws Exception {}

	@Override
	public void submitActual(int CID, boolean isCorrect, String actual) throws Exception {
		System.out.println("Submitted guess: isCorrect = " + isCorrect + "  actual = " + actual);
	}

	@Override
	public boolean updateCharacter(FictionalCharacter character) throws Exception {
		for(FictionalCharacter fc : characters){
			if(character.equals(fc)){
				
				if(character.getAppearsInTheseFictinalUniverses() != null){
					if(fc.getAppearsInTheseFictinalUniverses() == null){
						fc.setAppearsInTheseFictinalUniverses(character.getAppearsInTheseFictinalUniverses());
					}
					else{
						fc.getAppearsInTheseFictinalUniverses().addAll(character.getAppearsInTheseFictinalUniverses());
					}
				}
				
				if(character.getBasedOn() != null){
					if(fc.getBasedOn() == null){
						fc.setBasedOn(character.getBasedOn());
					}
					else{
						fc.getBasedOn().addAll(character.getBasedOn());
					}
				}
				
				if(character.getCharacterCreatedBy() != null){
					if(fc.getCharacterCreatedBy() == null){
						fc.setCharacterCreatedBy(character.getCharacterCreatedBy());
					}
					else{
						fc.getCharacterCreatedBy().addAll(character.getCharacterCreatedBy());
					}
				}
				
				if(character.getChildren() != null){
					if(fc.getChildren() == null){
						fc.setChildren(character.getChildren());
					}
					else{
						fc.getChildren().addAll(character.getChildren());
					}
				}
				
				if(character.getDateOfBirth() != null){
					if(fc.getDateOfBirth() == null){
						fc.setDateOfBirth(character.getDateOfBirth());
					}
					else{
						fc.setDateOfBirth(character.getDateOfBirth());
					}
				}
				
				if(character.getEducation() != null){
					if(fc.getEducation() == null){
						fc.setEducation(character.getEducation());
					}
					else{
						fc.getEducation().addAll(character.getEducation());
					}
				}
				
				if(character.getEmployers() != null){
					if(fc.getEmployers() == null){
						fc.setEmployers(character.getEmployers());
					}
					else{
						fc.getEmployers().addAll(character.getEmployers());
					}
				}
				
				if(character.getEthnicity() != null){
					if(fc.getEthnicity() == null){
						fc.setEthnicity(character.getEthnicity());
					}
					else{
						fc.getEthnicity().addAll(character.getEthnicity());
					}
				}
				
				if(character.getGender() != null){
					fc.setGender(character.getGender());		
				}
				
				if(character.getHasPossesed() != null){
					if(fc.getHasPossesed() == null){
						fc.setHasPossesed(character.getHasPossesed());
					}
					else{
						fc.getHasPossesed().addAll(character.getHasPossesed());
					}
				}
				
				if(character.getHeight() != null){
					if(fc.getHeight() == null){
						fc.setHeight(character.getHeight());
					}
				}
				
				if(character.getMarriedTo() != null){
					if(fc.getMarriedTo() == null){
						fc.setMarriedTo(character.getMarriedTo());
					}
					else{
						fc.getMarriedTo().addAll(character.getMarriedTo());
					}
				}
				
				if(character.getMedicalConditions() != null){
					if(fc.getMedicalConditions() == null){
						fc.setMedicalConditions(character.getMedicalConditions());
					}
					else{
						fc.getMedicalConditions().addAll(character.getMedicalConditions());
					}
				}
				
				if(character.getOccupation() != null){
					if(fc.getOccupation() == null){
						fc.setOccupation(character.getOccupation());
					}
					else{
						fc.getOccupation().addAll(character.getOccupation());
					}
				}
				
				if(character.getOrganizations() != null){
					if(fc.getOrganizations() == null){
						fc.setOrganizations(character.getOrganizations());
					}
					else{
						fc.getOrganizations().addAll(character.getOrganizations());
					}
				}
				
				if(character.getParents() != null){
					if(fc.getParents() == null){
						fc.setParents(character.getParents());
					}
					else{
						fc.getParents().addAll(character.getParents());
					}
				}
				
				if(character.getPlaceOfBirth() != null){
					if(fc.getPlaceOfBirth() == null){
						fc.setPlaceOfBirth(character.getPlaceOfBirth());
					}
					else{
						fc.getPlaceOfBirth().addAll(character.getPlaceOfBirth());
					}
				}
				
				if(character.getPlacesLived() != null){
					if(fc.getPlacesLived() == null){
						fc.setPlacesLived(character.getPlacesLived());
					}
					else{
						fc.getPlacesLived().addAll(character.getPlacesLived());
					}
				}
				
				if(character.getPowersOrAbilities() != null){
					if(fc.getPowersOrAbilities() == null){
						fc.setPowersOrAbilities(character.getPowersOrAbilities());
					}
					else{
						fc.getPowersOrAbilities().addAll(character.getPowersOrAbilities());
					}
				}
				
				if(character.getQuotations() != null){
					if(fc.getQuotations() == null){
						fc.setQuotations(character.getQuotations());
					}
					else{
						fc.getQuotations().addAll(character.getQuotations());
					}
				}
				
				if(character.getRank() != null){
					if(fc.getRank() == null){
						fc.setRank(character.getRank());
					}
					else{
						fc.getRank().addAll(character.getRank());
					}
				}
				
				if(character.getRomanticallyInvolvedWith() != null){
					if(fc.getRomanticallyInvolvedWith() == null){
						fc.setRomanticallyInvolvedWith(character.getRomanticallyInvolvedWith());
					}
					else{
						fc.getRomanticallyInvolvedWith().addAll(character.getRomanticallyInvolvedWith());
					}
				}
				
				if(character.getSiblings() != null){
					if(fc.getSiblings() == null){
						fc.setSiblings(character.getSiblings());
					}
					else{
						fc.getSiblings().addAll(character.getSiblings());
					}
				}
				
				if(character.getSpecies() != null){
					if(fc.getSpecies() == null){
						fc.setSpecies(character.getSpecies());
					}
					else{
						fc.getSpecies().addAll(character.getSpecies());
					}
				}
				
				if(character.getWeight() != null){
					if(fc.getWeight() == null){
						fc.setWeight(character.getWeight());
					}
				}
				
				return true;
			}
		}
		
		return false;
	}

	@Override
	public Pair<SortedSet<StatisticsEntry>, Integer> queryStatisticsHistory() throws Exception {
		SortedSet<StatisticsEntry> history = new TreeSet<StatisticsEntry>();
		history.add(new StatisticsEntry("Dan (Scala) Kilman", "Dan (Scala) Kilman", true, getNextTimeStamp()));
		history.add(new StatisticsEntry("Dan (Scala) Kilman", "Dan (Scala) Kilman", true, getNextTimeStamp()));
		history.add(new StatisticsEntry("Dan (Scala) Kilman", "Dan (Scala) Kilman", true, getNextTimeStamp()));
		history.add(new StatisticsEntry("Dan (Scala) Kilman", "Nir (TV) Biran", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Dan (Scala) Kilman", "Nir (TV) Biran", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Dan (Scala) Kilman", "Alon", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Nir (TV) Biran", "Nir (TV) Biran", true, getNextTimeStamp()));
		history.add(new StatisticsEntry("Nir (TV) Biran", "Nir (TV) Biran", true, getNextTimeStamp()));
		history.add(new StatisticsEntry("Nir (TV) Biran", "Dan (Scala) Kilman", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Nir (TV) Biran", "Dan (Scala) Kilman", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Nir (TV) Biran", "Alon", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Alon", "Dan (Scala) Kilman", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Alon", "Nir (TV) Biran", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Alon", "Ofer", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Alon", "Ofer", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Ofer", "Nir (TV) Biran", false, getNextTimeStamp()));
		history.add(new StatisticsEntry("Ofer", "Ofer", true, getNextTimeStamp()));
		history.add(new StatisticsEntry("Ofer", "Ofer", true, getNextTimeStamp()));
		history.add(new StatisticsEntry("Ofer", "Ofer", true, getNextTimeStamp()));	
		
		int counter = 0;
		for (StatisticsEntry statisticsEntry : history) {
			if (statisticsEntry.isCorrect()) {
				counter++;
			}
		}
		return new Pair<SortedSet<StatisticsEntry>, Integer>(history, counter);
	}
	
	private Date getNextTimeStamp() {
		lastTimeStamp = new Date(lastTimeStamp.getTime() - 100000);
		return lastTimeStamp;
	}

	@Override
	public void garbageCollection() throws Exception { }

    @Override
    public int getNewGUISessionID() throws SQLException {
        return 0;
    }

    @Override
    public void cleanGUISession(int majorSID) throws SQLException { }

    @Override
    public boolean requestEditMode(int majorSID) throws SQLException {
        return true;
    }

    @Override
    public void endEditMode(int majorSID) throws SQLException { }

    @Override
    public boolean importToDB(File freeBaseRoot) throws Exception {
        return false;
    }

    @Override
    public void close() throws Exception { }

    @Override
    public void forceGuiSessionCleanup(int guiSessionID) throws Exception { }

	@Override
	public boolean isCleanDB() throws Exception {
		// TODO ALON Auto-generated method stub
		return false;
	}
}
